package top.natsu.reminder.hook;


import com.sun.jna.Structure;
import com.sun.jna.examples.win32.Kernel32;
import com.sun.jna.examples.win32.User32;
import com.sun.jna.examples.win32.User32.HHOOK;
import com.sun.jna.examples.win32.User32.HOOKPROC;
import com.sun.jna.examples.win32.User32.MSG;
import com.sun.jna.examples.win32.W32API.HMODULE;
import com.sun.jna.examples.win32.W32API.LRESULT;
import com.sun.jna.examples.win32.W32API.WPARAM;
import top.natsu.reminder.common.constant.HookType;
import top.natsu.reminder.handler.TimeRecord;

import java.io.BufferedWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * 鼠标钩子
 *
 * @author shikanatsu
 */
public class MouseHook implements Runnable {

    public static final int WM_MOUSEMOVE = 512;
    private static HHOOK hhk;
    private static LowLevelMouseProc mouseHook;
    final static User32 lib = User32.INSTANCE;
    private volatile boolean isStart = false;

    private TimeRecord timeRecord;


    public MouseHook(boolean isStart, TimeRecord timeRecord) {
        this.isStart = isStart;
        this.timeRecord = timeRecord;
    }

    public interface LowLevelMouseProc extends HOOKPROC {
        LRESULT callback(int nCode, WPARAM wParam, MOUSEHOOKSTRUCT lParam);
    }

    public static class MOUSEHOOKSTRUCT extends Structure {
        @Override
        protected List<String> getFieldOrder() {
            return null;
        }

        public static class ByReference extends MOUSEHOOKSTRUCT implements
                Structure.ByReference {
            @Override
            protected List<String> getFieldOrder() {
                return null;
            }
        }

        ;
        public User32.POINT pt;
        public int wHitTestCode;
        public User32.ULONG_PTR dwExtraInfo;
    }

    @Override
    public void run() {
        HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null);
        mouseHook = new LowLevelMouseProc() {
            @Override
            public LRESULT callback(int nCode, WPARAM wParam, MOUSEHOOKSTRUCT info) {
                SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd");
                SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String fileName = df1.format(new Date());
                String time = df2.format(new Date());
                BufferedWriter bw1 = null;
                BufferedWriter bw2 = null;

//                System.out.println("鼠标输出->"+info.pt);

                timeRecord.setOperation(new Date(), HookType.MOUSE);

//                try {
//                    bw1=new BufferedWriter(new FileWriter(new File(".//log//"+fileName+"_Mouse.txt"),true));
//                    bw2=new BufferedWriter(new FileWriter(new File(".//log//"+fileName+"_Common.txt"),true));
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//                if (isStart == false) {
//                    System.exit(0);
//                }
//                if (nCode >= 0) {
//                    switch (wParam.intValue()) {
//                        case MouseHook.WM_MOUSEMOVE:
//                            try {
//                                bw1.write(time+"  ####  "+"x=" + info.pt.x
//                                        + " y=" + info.pt.y+"\r\n");
//                                bw2.write(time+"  ####  "+"x=" + info.pt.x
//                                        + " y=" + info.pt.y+"\r\n");
//                                bw1.flush();
//                                bw2.flush();
//                            } catch (IOException e) {
//                                e.printStackTrace();
//                            }
//                    }
//                }
                return lib
                        .CallNextHookEx(hhk, nCode, wParam, info.getPointer());
            }
        };
        hhk = lib.SetWindowsHookEx(User32.WH_MOUSE_LL, mouseHook, hMod, 0);
        int result;
        MSG msg = new MSG();
        while ((result = lib.GetMessage(msg, null, 0, 0)) != 0) {
            if (result == -1) {
                System.err.println("error in get message");
                break;
            } else {
                System.err.println("got message");
                lib.TranslateMessage(msg);
                lib.DispatchMessage(msg);
            }
        }
        lib.UnhookWindowsHookEx(hhk);
    }
}